package com.zzyl.nursing.service.impl;

import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.List;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.IdcardUtil;
import com.alibaba.fastjson2.JSON;
import com.zzyl.common.constant.CacheConstants;
import com.zzyl.common.exception.base.BaseException;
import com.zzyl.common.utils.DateUtils;
import com.zzyl.common.utils.StringUtils;
import com.zzyl.framework.ai.AiInvoke;
import com.zzyl.nursing.domain.dto.HealthAssessmentDto;
import com.zzyl.nursing.vo.health.HealthReportVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import com.zzyl.nursing.mapper.HealthAssessmentMapper;
import com.zzyl.nursing.domain.HealthAssessment;
import com.zzyl.nursing.service.IHealthAssessmentService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;

/**
 * 健康评估Service业务层处理
 *
 * @author ruoyi
 * @date 2025-05-20
 */
@Service
@Slf4j
public class HealthAssessmentServiceImpl extends ServiceImpl<HealthAssessmentMapper, HealthAssessment> implements IHealthAssessmentService {

    @Autowired
    private HealthAssessmentMapper healthAssessmentMapper;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private AiInvoke aiInvoke;

    /**
     * 查询健康评估
     *
     * @param id 健康评估主键
     * @return 健康评估
     */
    @Override
    public HealthAssessment selectHealthAssessmentById(Long id) {
        return getById(id);
    }

    /**
     * 查询健康评估列表
     *
     * @param healthAssessment 健康评估
     * @return 健康评估
     */
    @Override
    public List<HealthAssessment> selectHealthAssessmentList(HealthAssessment healthAssessment) {
        return healthAssessmentMapper.selectHealthAssessmentList(healthAssessment);
    }

    /**
     * 新增健康评估
     *
     * @param dto 健康评估
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public long insertHealthAssessment(HealthAssessmentDto dto) {
        // 1.参数校验
        log.info("1.开始参数校验！");
        dtoParamCheck(dto);

        log.info("2.在Redis中读取体检报告PDF内容！");
        // 2.在Redis中读取体检报告PDF内容,并判断是否为空
        String pdfText = (String) redisTemplate.opsForHash().get(CacheConstants.HEALTH_ASSESSMENT_TEXT_KEY, dto.getIdCard());
        if (StringUtils.isBlank(pdfText)) {
            throw new BaseException("体检DPF报告信息为上传");
        }

        log.info("3.读取prompt.txt中模块内容！");
        // 3.在resources下读取prompt.txt中模块内容
        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("prompt.txt");
        String aiTemplate = IoUtil.read(inputStream, StandardCharsets.UTF_8);
        if (StringUtils.isBlank(aiTemplate)) {
            throw new BaseException("提示词模板文件不存在");
        }

        log.info("4.组织prompt提示词！");
        // 4.组织prompt提示词
        String prompt = aiTemplate.replace("prompt", pdfText);

        log.info("5.调用千帆AI接口，获取结果并且判断结果是否为空！");
        // 5.调用千帆AI接口，获取结果并且判断结果是否为空
        String healthResult = aiInvoke.invokeQianFanChat(prompt);
        if (StringUtils.isBlank(healthResult)) {
            throw new BaseException("AI生成为空！");
        }

        log.info("6.解析JSON字符串到VO对象中");
        // 6.解析JSON字符串到VO对象中
        HealthReportVo healthReportVo = JSON.parseObject(healthResult, HealthReportVo.class);

        log.info("7.新增健康评估表中的数据，并返回表中自增的主键Id");
        // 7.新增健康评估表中的数据，并返回表中自增的主键Id
        long id = saveHealthAssessment(dto, healthReportVo);

        log.info("8.删除Redis中缓存的体检报告信息");
        // 8.删除Redis中缓存的体检报告信息
        redisTemplate.opsForHash().delete(CacheConstants.HEALTH_ASSESSMENT_TEXT_KEY, dto.getIdCard());

        log.info("9.返回主键Id");
        // 9.返回主键Id
        return id;
    }


    /**
     * 保存健康评估表数据
     *
     * @param dto
     * @param aiResultVo
     * @return
     */
    private long saveHealthAssessment(HealthAssessmentDto dto, HealthReportVo aiResultVo) {
        // 1.数据封装
        // 1.1 DTO传入的封装
        HealthAssessment assessment = new HealthAssessment();
        // 老人姓名
        assessment.setElderName(dto.getElderName());
        // 老人身份证号
        assessment.setIdCard(dto.getIdCard());
        // 体检机构
        assessment.setPhysicalExamInstitution(dto.getPhysicalExamInstitution());
        // 体检报告URL
        assessment.setPhysicalReportUrl(dto.getPhysicalReportUrl());

        // 1.2 糊涂工具类根据身份证来计算年龄等信息,注意时间格式
        // 出生日期
        assessment.setBirthDate(IdcardUtil.getBirthDate(dto.getIdCard()).toLocalDateTime());
        // 年龄
        assessment.setAge(IdcardUtil.getAgeByIdCard(dto.getIdCard()));
        // 性别(0男 1女)
        assessment.setGender(IdcardUtil.getGenderByIdCard(dto.getIdCard()));

        // 1.3 AI数据获取
        // 健康评分
        assessment.setHealthScore(String.valueOf(aiResultVo.getHealthAssessment().getHealthIndex()));
        // 总检日期
        assessment.setTotalCheckDate(aiResultVo.getTotalCheckDate());
        // 评分结果
        assessment.setRiskLevel(aiResultVo.getHealthAssessment().getRiskLevel());
        // 报告总结
        assessment.setReportSummary(aiResultVo.getSummarize());
        // 疾病风险-转为JSON格式数据
        assessment.setDiseaseRisk(JSON.toJSONString(aiResultVo.getRiskDistribution()));
        // 异常分析-转为JSON格式数据
        assessment.setAbnormalAnalysis(JSON.toJSONString(aiResultVo.getAbnormalData()));
        // 健康系统分值-转为JSON格式数据
        assessment.setSystemScore(JSON.toJSONString(aiResultVo.getSystemScore()));
        //是否建议入住（0：建议  1：不建议）
        assessment.setSuggestionForAdmission(aiResultVo.getRiskDistribution().getHealthy() >= 60 ? 0 : 1);
        //推荐的护理等级
        assessment.setNursingLevelName(levelOpinion(aiResultVo));
        //入住情况（0-已入住，1-未入住）
        assessment.setAdmissionStatus(1);
        //评估时间
        assessment.setAssessmentTime(LocalDateTime.now());

        // 2.插入数据库中
        boolean save = this.save(assessment);
        if (!save) {
            throw new BaseException("新增智能体检报告失败！");
        }

        log.info("返回自增主键数据:{}", assessment.getId());
        // 3.返回自增主键数据
        return assessment.getId();
    }

    /**
     * 评论等级
     *
     * @param aiResultVo
     * @return
     */
    private String levelOpinion(HealthReportVo aiResultVo) {
        if (aiResultVo.getHealthAssessment().getHealthIndex() < 0 || aiResultVo.getHealthAssessment().getHealthIndex() > 100) {
            throw new BaseException("健康评分数据异常！");
        }
        if (aiResultVo.getHealthAssessment().getHealthIndex() >= 90) {
            return "三级护理";
        } else if (aiResultVo.getHealthAssessment().getHealthIndex() >= 80) {
            return "二级护理";
        } else if (aiResultVo.getHealthAssessment().getHealthIndex() >= 70) {
            return "一级护理";
        } else if (aiResultVo.getHealthAssessment().getHealthIndex() >= 60) {
            return "特级护理";
        } else {
            return "不建议入住！";
        }
    }

    /**
     * 参数校验
     *
     * @param dto
     */
    private void dtoParamCheck(HealthAssessmentDto dto) {
        // 老人姓名校验
        if (StringUtils.isBlank(dto.getElderName()) || "null".equals(dto.getElderName())) {
            throw new BaseException("老人姓名不能为空！");
        }

        // 老人身份证校验
        if (StringUtils.isBlank(dto.getIdCard()) || "null".equals(dto.getIdCard())) {
            throw new BaseException("老人身份证校验不能为空！");
        }

        // 体检机构参数校验
        if (StringUtils.isBlank(dto.getPhysicalExamInstitution()) || "null".equals(dto.getPhysicalExamInstitution())) {
            throw new BaseException("体检机构参数校验为空！");
        }

        // 体检报告URL参数校验
        if (StringUtils.isBlank(dto.getPhysicalReportUrl()) || "null".equals(dto.getPhysicalReportUrl())) {
            throw new BaseException("体检报告URL参数校验为空！");
        }
    }

    /**
     * 修改健康评估
     *
     * @param healthAssessment 健康评估
     * @return 结果
     */
    @Override
    public int updateHealthAssessment(HealthAssessment healthAssessment) {
        return updateById(healthAssessment) ? 1 : 0;
    }

    /**
     * 批量删除健康评估
     *
     * @param ids 需要删除的健康评估主键
     * @return 结果
     */
    @Override
    public int deleteHealthAssessmentByIds(Long[] ids) {
        return removeByIds(Arrays.asList(ids)) ? 1 : 0;
    }

    /**
     * 删除健康评估信息
     *
     * @param id 健康评估主键
     * @return 结果
     */
    @Override
    public int deleteHealthAssessmentById(Long id) {
        return removeById(id) ? 1 : 0;
    }
}
